package com.qire.common.dal.base;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.cache.CacheMode;
import com.lzy.okgo.callback.Callback;
import com.lzy.okgo.model.HttpParams;
import com.lzy.okgo.model.Progress;
import com.lzy.okgo.model.Response;
import com.lzy.okgo.request.base.Request;
import com.lzy.okgo.utils.OkLogger;

import com.qire.antsbinder.dal.AntsDataWarehouse;
import com.qire.antsbinder.dal.exception.ExceptionObservable;

import com.qire.common.dal.exception.EmptyDataException;
import com.qire.common.dal.exception.FormatDataException;
import com.qire.common.dal.exception.NetworkException;
import com.qire.common.dal.exception.NullResponseWrapperException;

import java.io.File;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Set;

import okhttp3.ResponseBody;

/**
 * 基于AntsDataWarehouse实现的网络请求数据仓库
 //@param <ResponseWrapper>
 */
//public class BaseNetworkAccessWarehouse<T extends ResponseWrapper> extends AntsDataWarehouse implements Callback<T> {
public class BaseNetworkAccessWarehouse extends AntsDataWarehouse implements Callback<ResponseWrapper> {

    private static final long InvalidTime = -1;

    protected final HashMap<String,Type> resultTypeMap = new HashMap<>();


    @Override
    public void getData(String url, HashMap<String,Object> map, MethodType methodType, WarehouseCacheMode mWarehouseCacheMode, long cacheTime, Type resultType) {
        if(!resultTypeMap.containsKey(url)){
            resultTypeMap.put(url,resultType);
        }
        switch (methodType){
            case GET:
                execute(OkGo.get(url),url,map,conversionCacheMode(mWarehouseCacheMode),cacheTime);
                break;
            case POST:
                execute(OkGo.post(url),url,map,conversionCacheMode(mWarehouseCacheMode),cacheTime);
                break;
        }
    }

    private void execute(Request request,String url, HashMap<String,Object> map, CacheMode cacheMode,long cacheTime){
        HttpParams httpParams = null;
        if(map !=  null) {
            Set<String> keys = map.keySet();
            httpParams = new HttpParams();
            for (String key : keys) {
                Object value = map.get(key);
                if(value instanceof File) {
                    httpParams.put(key, (File) value);
                } else if(value instanceof File[]) {
                    File[] files = (File[]) value;
                    for(int index = 0; index < files.length; index++) {
                        httpParams.put(key + index, files[index]);
                    }
                } else {
                    httpParams.put(key, value.toString());
                }
            }
        }
        request.params(httpParams)
                .cacheMode(cacheMode)
                .tag(url);
        if(cacheTime==InvalidTime)
            request.cacheTime(cacheTime);
        request.execute(this);
    }

    @Override
    public void cancel(){
        OkGo.getInstance().cancelTag(this);
    }

    @Override
    public void onStart(Request<ResponseWrapper, ? extends Request> request) {
        sign(request.getParams());
    }

    @Override
    public void onSuccess(Response<ResponseWrapper> response) {
        if(!checkRepStatus(response)){
            return;
        }
        handleSuccess(response);
    }

    /**
     * 检查接口返回状态是否异常
     * @param response
     */
    protected boolean checkRepStatus(Response<ResponseWrapper> response){

        // 在post和get时指定的tag参数，使用了URL作为tag详情见当前类的get()和post()方法
        String tagUrl = (String) response.getRawResponse().request().tag();
        // 增加了服务器时间同步 syncServiceTime()，用于后续的业务处理。原本值到 body()
        ResponseWrapper responseWrapper = response.body().syncServiceTime();

        if(responseWrapper == null){
            NullResponseWrapperException exception = new NullResponseWrapperException(tagUrl);
            exception.requestUrl = tagUrl;
            exception.extraMsg = response.message();
            ExceptionObservable.notifyObservers(exception);
            return false;
        }

        if(responseWrapper.isIllegal()){
            responseWrapper.illegalExceptionHandle(tagUrl);
            return false;
        }

        return true;
    }

    @Override
    public void onCacheSuccess(Response<ResponseWrapper> response) {
        handleSuccess(response);
    }

    private void handleSuccess(Response<ResponseWrapper> response){
        //在post和get时指定的tag参数，使用了URL作为tag详情见当前类的get()和post()方法
        String tagUrl = (String) response.getRawCall().request().tag();
        ResponseWrapper body;
        try{
            body = response.body();
        } catch (ClassCastException e){
            e.printStackTrace();
            return;
        }
        if(body == null) return;
        Gson gson = new Gson();
        Object tmpData = body.getData();
        if(tmpData == null){
            EmptyDataException emptyDataException = new EmptyDataException(tagUrl);
            emptyDataException.extraMsg = "ResponseWrapper.data数据为null";
            ExceptionObservable.notifyObservers(emptyDataException);
            return;
        }
        try {
            Type resultType = resultTypeMap.get(tagUrl);
            Object data = gson.fromJson(gson.toJson(tmpData), resultType);
            if(verifyResponseData(data))
                notice(tagUrl,data,response.isFromCache());
        } catch (JsonSyntaxException e){
            e.printStackTrace();
            FormatDataException formatDataException = new FormatDataException(tagUrl);
            formatDataException.extraMsg = "json格式错误";
            ExceptionObservable.notifyObservers(formatDataException);
        }
    }

    protected boolean verifyResponseData(Object data){
        if(data == null) {
            return false;
        }
//        Field[] fields = data.getClass().getDeclaredFields();
//        for (Field field : fields){
//            try {
//                if(field.isAnnotationPresent())
//                    continue;
//                Object obj = field.get(data);
//                if(obj== null){
//                    return false;
//                }
//            } catch (IllegalAccessException e) {
//                e.printStackTrace();
//            }
//        }
        return true;
    }

    @Override
    public void onError(Response<ResponseWrapper> response) {
        //在post和get时指定的tag参数，使用了URL作为tag详情见当前类的get()和post()方法
        String tagUrl = (String) response.getRawCall().request().tag();
        OkLogger.printStackTrace(response.getException());
        NetworkException exception = new NetworkException(tagUrl);
        exception.requestUrl = tagUrl;
        exception.extraMsg = "网络异常哦";
        ExceptionObservable.notifyObservers(exception);
    }

    @Override
    public void onFinish() {
    }

    @Override
    public void uploadProgress(Progress progress) {}

    @Override
    public void downloadProgress(Progress progress) {}

    @Override
    public ResponseWrapper convertResponse(okhttp3.Response response) throws Throwable {
        ResponseBody body = response.body();
        if(body == null) return null;

        Gson gson = new Gson();
        JsonReader jsonReader = new JsonReader(body.charStream());

        return gson.fromJson(jsonReader, new TypeToken<ResponseWrapper>(){}.getType());
    }

    public CacheMode conversionCacheMode(WarehouseCacheMode mWarehouseCacheMode){
        switch (mWarehouseCacheMode){
            case DEFAULT:
                return CacheMode.DEFAULT;
            case NO_CACHE:
                return CacheMode.NO_CACHE;
            case REQUEST_FAILED_READ_CACHE:
                return CacheMode.REQUEST_FAILED_READ_CACHE;
            case IF_NONE_CACHE_REQUEST:
                return CacheMode.IF_NONE_CACHE_REQUEST;
            case FIRST_CACHE_THEN_REQUEST:
                return CacheMode.FIRST_CACHE_THEN_REQUEST;
        }
        return CacheMode.DEFAULT;
    }

    protected void sign(HttpParams params){
        Signer.sign(params);
    }

}
